<template>
  <el-drawer
    v-model="drawerVisible"
    :direction="direction"
    :size="drawerSize"
    :with-header="withHeader"
    :show-close="showClose"
    :modal="modal"
    :close-on-click-modal="closeOnClickModal"
    :close-on-press-escape="closeOnPressEscape"
    :append-to-body="appendToBody"
    :append-to="appendTo"
    :lock-scroll="lockScroll"
    :before-close="handleBeforeClose"
    :z-index="zIndex"
    :custom-class="customClass"
    :header-class="headerClass"
    :body-class="bodyClass"
    :footer-class="footerClass"
    :modal-class="modalClass"
    :title="title"
    :open-delay="openDelay"
    :close-delay="closeDelay"
    :modal-penetrable="modalPenetrable"
    :resizable="resizable"
    :header-aria-level="headerAriaLevel"
    :destroy-on-close="destroyOnClose"
    @open="handleOpen"
    @opened="handleOpened"
    @close="handleClose"
    @closed="handleClosed"
    @open-auto-focus="handleOpenAutoFocus"
    @close-auto-focus="handleCloseAutoFocus"
    @resize-start="handleResizeStart"
    @resize="handleResize"
    @resize-end="handleResizeEnd"
  >
    <template #header>
      <slot name="header">
        <div class="drawer-header-wrapper">
          <div class="drawer-actions">
            <button
              class="drawer-action-btn"
              @click="handleFullscreenToggle"
              :title="props.fullscreen ? '退出全屏' : '全屏'"
            >
              <i
                :class="
                  props.fullscreen
                    ? 'i-ri-fullscreen-exit-line'
                    : 'i-ri-fullscreen-line'
                "
              ></i>
            </button>
            <button
              class="drawer-action-btn"
              @click="handleCloseClick"
              title="关闭"
            >
              <i class="i-ri-close-line"></i>
            </button>
          </div>
        </div>
      </slot>
    </template>
    <template v-if="$slots.default" #default>
      <slot></slot>
    </template>
    <template v-if="$slots.footer" #footer>
      <slot name="footer"></slot>
    </template>
  </el-drawer>
</template>

<script setup lang="ts">
import { computed } from 'vue'
import type { DrawerProps as ElDrawerProps } from 'element-plus'

defineOptions({ name: 'Drawer' })

export interface DrawerProps {
  /**
   * @description 是否显示抽屉
   */
  modelValue?: boolean
  /**
   * @description 抽屉的方向
   */
  direction?: ElDrawerProps['direction']
  /**
   * @description 抽屉的大小
   */
  size?: string | number
  /**
   * @description 是否显示头部
   */
  withHeader?: boolean
  /**
   * @description 是否显示关闭按钮
   */
  showClose?: boolean
  /**
   * @description 是否显示遮罩层
   */
  modal?: boolean
  /**
   * @description 点击遮罩层是否关闭
   */
  closeOnClickModal?: boolean
  /**
   * @description 按 ESC 键是否关闭
   */
  closeOnPressEscape?: boolean
  /**
   * @description 是否将抽屉插入到 body 元素上
   */
  appendToBody?: boolean
  /**
   * @description 挂载到哪个 DOM 元素
   */
  appendTo?: string | HTMLElement
  /**
   * @description 是否在打开抽屉时将 body 滚动锁定
   */
  lockScroll?: boolean
  /**
   * @description 关闭前的回调
   */
  beforeClose?: (done: () => void) => void
  /**
   * @description 设置 z-index
   */
  zIndex?: number
  /**
   * @description 自定义类名（已废弃，建议使用 class）
   */
  customClass?: string
  /**
   * @description header 部分的自定义 class 名
   */
  headerClass?: string
  /**
   * @description body 部分的自定义 class 名
   */
  bodyClass?: string
  /**
   * @description footer 部分的自定义 class 名
   */
  footerClass?: string
  /**
   * @description 遮罩层的自定义类名
   */
  modalClass?: string
  /**
   * @description Drawer 的标题
   */
  title?: string
  /**
   * @description Drawer 打开的延时时间，单位毫秒
   */
  openDelay?: number
  /**
   * @description Drawer 关闭的延时时间，单位毫秒
   */
  closeDelay?: number
  /**
   * @description 是否允许穿透遮罩层
   */
  modalPenetrable?: boolean
  /**
   * @description 为抽屉启用可调整大小的功能
   */
  resizable?: boolean
  /**
   * @description header 的 aria-level 属性
   */
  headerAriaLevel?: string
  /**
   * @description 当关闭时将销毁子元素
   */
  destroyOnClose?: boolean
  /**
   * @description 是否全屏
   */
  fullscreen?: boolean
}

const props = withDefaults(defineProps<DrawerProps>(), {
  modelValue: false,
  direction: 'rtl',
  size: '50%',
  withHeader: true,
  showClose: false,
  modal: true,
  closeOnClickModal: true,
  closeOnPressEscape: true,
  appendToBody: true,
  appendTo: undefined,
  lockScroll: true,
  destroyOnClose: false,
  headerClass: 'custom-drawer-header',
  bodyClass: undefined,
  footerClass: undefined,
  modalClass: undefined,
  title: undefined,
  openDelay: 0,
  closeDelay: 0,
  modalPenetrable: false,
  resizable: false,
  headerAriaLevel: '2',
  fullscreen: false,
})

const emit = defineEmits<{
  /**
   * @description 更新显示状态
   */
  'update:modelValue': [value: boolean]
  /**
   * @description 更新全屏状态
   */
  'update:fullscreen': [value: boolean]
  /**
   * @description Drawer 打开的回调
   */
  open: []
  /**
   * @description Drawer 打开动画结束时的回调
   */
  opened: []
  /**
   * @description Drawer 关闭的回调
   */
  close: []
  /**
   * @description Drawer 关闭动画结束时的回调
   */
  closed: []
  /**
   * @description 输入焦点聚焦在 Drawer 内容时的回调
   */
  openAutoFocus: []
  /**
   * @description 输入焦点从 Drawer 内容失焦时的回调
   */
  closeAutoFocus: []
  /**
   * @description 当开始调整大小时触发（当启用 resizable 时）
   * @param evt 鼠标事件
   * @param size 调整后的大小
   */
  resizeStart: [evt: MouseEvent, size: number]
  /**
   * @description 调整大小时触发（启用 resizable 时）
   * @param evt 鼠标事件
   * @param size 调整后的大小
   */
  resize: [evt: MouseEvent, size: number]
  /**
   * @description 当调整大小结束时触发（当启用 resizable 时）
   * @param evt 鼠标事件
   * @param size 调整后的大小
   */
  resizeEnd: [evt: MouseEvent, size: number]
}>()

/**
 * @description 抽屉显示状态
 */
const drawerVisible = computed({
  get: () => props.modelValue,
  set: value => {
    emit('update:modelValue', value)
  },
})

/**
 * @description 抽屉大小
 */
const drawerSize = computed(() => {
  if (props.fullscreen) {
    return '100%'
  }
  return props.size
})

/**
 * @description 处理打开
 */
const handleOpen = () => {
  emit('open')
}

/**
 * @description 处理打开后
 */
const handleOpened = () => {
  emit('opened')
}

/**
 * @description 处理关闭
 */
const handleClose = () => {
  emit('close')
}

/**
 * @description 处理关闭后
 */
const handleClosed = () => {
  emit('closed')
}

/**
 * @description 处理打开自动聚焦
 */
const handleOpenAutoFocus = () => {
  emit('openAutoFocus')
}

/**
 * @description 处理关闭自动聚焦
 */
const handleCloseAutoFocus = () => {
  emit('closeAutoFocus')
}

/**
 * @description 处理调整大小开始
 * @param evt 鼠标事件
 * @param size 调整后的大小
 */
const handleResizeStart = (evt: MouseEvent, size: number) => {
  emit('resizeStart', evt, size)
}

/**
 * @description 处理调整大小
 * @param evt 鼠标事件
 * @param size 调整后的大小
 */
const handleResize = (evt: MouseEvent, size: number) => {
  emit('resize', evt, size)
}

/**
 * @description 处理调整大小结束
 * @param evt 鼠标事件
 * @param size 调整后的大小
 */
const handleResizeEnd = (evt: MouseEvent, size: number) => {
  emit('resizeEnd', evt, size)
}

/**
 * @description 处理关闭按钮点击
 */
const handleCloseClick = () => {
  drawerVisible.value = false
}

/**
 * @description 处理全屏切换
 */
const handleFullscreenToggle = () => {
  emit('update:fullscreen', !props.fullscreen)
}

/**
 * @description 处理关闭前
 */
const handleBeforeClose = (done: () => void) => {
  if (props.beforeClose) {
    props.beforeClose(done)
  } else {
    done()
  }
}
</script>

<style lang="scss" scoped>
.drawer-header-wrapper {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  width: 100%;
  height: auto;
  min-height: 32px;
  // 确保 header 不会影响拖拽区域（拖拽区域在抽屉边缘）
  pointer-events: none;

  .drawer-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    // 恢复按钮组的指针事件，使其可点击
    pointer-events: auto;
    flex-shrink: 0;
  }

  .drawer-action-btn {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: transparent;
    border: none;
    color: #64748b;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all 0.2s;
    padding: 0;
    margin: 0;

    &:hover {
      background: #f1f5f9;
      color: #1e293b;
    }

    &:active {
      transform: scale(0.95);
    }

    i {
      font-size: 18px;
    }
  }
}
</style>

<style lang="scss">
.custom-drawer-header {
  margin-bottom: 0 !important;
  padding: 12px 20px !important;
}

.custom-drawer-header + .el-drawer__body {
  padding-top: 0 !important;
}
</style>
